package com.example.prom.qianduoduo.y2025.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.example.prom.qianduoduo.y2025.model.MedicineInfo;
import com.example.prom.qianduoduo.y2025.model.MedicineInstruction;
import com.example.prom.qianduoduo.y2025.parser.MedicineHtmlParser;
import com.example.prom.strategy.excel.CustomCellStyleStrategy;
import com.example.prom.strategy.excel.CustomColumnWidthStrategy;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import static com.example.prom.qianduoduo.y2025.controller.BaseController.getWebDriver;
import static com.example.prom.qianduoduo.y2025.controller.BaseController.newWebDriverWait;

/**
 * Description
 *
 * @author DangWen
 */
@Slf4j
public class YaozhController2 {
    /**
     * https://db.yaozh.com/instruct?comprehensivesearchcontent=%E4%B9%9D%E5%91%B3%E7%BE%8C%E6%B4%BB%E4%B8%B8&
     * 1.遍历所有药品名称
     * 2.将年份最新的数据爬取到excel或者提供下载链接
     * 3.每次出发验证码，需要重新获取一次cookie
     */

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        String outputPath = "D:\\dangwen\\钱多多\\同事\\药品数据爬取"+System.currentTimeMillis()+".xlsx" ;
        List<MedicineInfo> medicineInfos = readExcel("D:\\dangwen\\钱多多\\同事\\药品目录-dataChange.xlsx");
//        List<MedicineInfo> medicineInfos = readExcel("D:\\dangwen\\钱多多\\同事\\药品目录 - 副本.xlsx");
        List<MedicineInfo> medicineInfoResults = new ArrayList<>();
        List<MedicineInstruction> noDataResults = new ArrayList<>();
        try {
            int total = medicineInfos.size();
            log.info("开始爬取数据... 总数据量为：{}", medicineInfos.size());
            for (int i = 0; i < total; i++) {
                // 添加延迟防止被封
                Thread.sleep(700 + new Random().nextInt(700));
                MedicineInfo medicineInfo = medicineInfos.get(i);
                String medicineName = medicineInfo.getMedicineName();
                int current = i + 1;
                // 打印进度信息
                String elapsedTime = formatElapsedTime(System.currentTimeMillis() - startTime);
                String progressMsg = String.format("正在爬取进度: %d/%d (%.1f%%) - 药品: %s - 耗时: %s",
                        current, total, (current * 100.0 / total), medicineName, elapsedTime);
                log.info(progressMsg);
                // 1.遍历所有药品名称
                // 2.将年份最新的数据爬取到excel或者提供下载链接
                String cookie = "Path=/; kztoken=nJail6zJp6iXaJqWmW5lZGRxapuW; his=a%3A10%3A%7Bi%3A0%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGFxapiX%22%3Bi%3A1%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGFxapmV%22%3Bi%3A2%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGFxapma%22%3Bi%3A3%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRpYpiW%22%3Bi%3A4%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRuZZWa%22%3Bi%3A5%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRxapib%22%3Bi%3A6%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRxapmY%22%3Bi%3A7%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRxapqV%22%3Bi%3A8%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRxapqb%22%3Bi%3A9%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lZGRxapuW%22%3B%7D; Hm_tf_k8xnbso1idm=1752673184; __bid_n=19813766fbc06248994ca7; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221981376709c220-0cef6cca8d731c8-26011e51-2073600-1981376709d9b4%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTk4MTM3NjcwOWMyMjAtMGNlZjZjY2E4ZDczMWM4LTI2MDExZTUxLTIwNzM2MDAtMTk4MTM3NjcwOWQ5YjQifQ%3D%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%22%2C%22value%22%3A%22%22%7D%2C%22%24device_id%22%3A%221981376709c220-0cef6cca8d731c8-26011e51-2073600-1981376709d9b4%22%7D; Hm_lvt_65968db3ac154c3089d7f9a4cbb98c94=1753105623; _ga=GA1.1.282458238.1752673184; _ga_FKHKQM5HWS=GS2.2.s1753105623$o1$g1$t1753105623$j60$l0$h0; yaozh_logintime=1753105831; yaozh_logintime_ext=1753105831; yaozh_user=1537877%09yaozh_15201065686; yaozh_user_ext=1537877%09yaozh_15201065686; yaozh_userId=1537877; yaozh_userId_ext=1537877; yaozh_jobstatus=kptta67UcJieW6zKnFSe2JyYnoaSbJhsnZucg26qb21rg66flM6bh5%2BscZJvbIXew9DezMBommeVlZWXaG1tblOcrGtsm1jRxayrwKyb0Mq59Bf914E8064150A2f8C35f5eeF11fa6EnNeekmefV5abmpRjb2xoaJdbbKabap%2BGraDOnVSe2JySl56DaJxqmJWVlmtqZmxqmltssA%3D%3D53b8bc239ecb64f4369d0d486cca0327; _ga=GA1.3.282458238.1752673184; _gid=GA1.3.2103832457.1753105615; _c_WBKFRo=POXx8UcSMXP2Zk0qz9yks5JlgxPBqgLC0fLRxItx; PHPSESSID=cuj3fpiq9moq9a1fk7vn22ra56; Path=/; Hm_lvt_19d20990a54a49c29ef6894ac385ed90=1753244143,1753319659,1753321915,1753353167; HMACCOUNT=8134B8F59C308B5F; Hm_lvt_be8cc362c4e40bc680a230dd3610a66f=1753244144,1753319659,1753321915,1753353167;";
//                String cooke = "Path=/; kztoken=nJail6zJp6iXaJqWmW5lYmdwYZma; his=a%3A10%3A%7Bi%3A0%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdraJOX%22%3Bi%3A1%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdraJOb%22%3Bi%3A2%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdraJSV%22%3Bi%3A3%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdraJyT%22%3Bi%3A4%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdraJyY%22%3Bi%3A5%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdtapuV%22%3Bi%3A6%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdtapyY%22%3Bi%3A7%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmduYZOS%22%3Bi%3A8%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmduYZOY%22%3Bi%3A9%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdwYZma%22%3B%7D; Hm_tf_k8xnbso1idm=1752673184; __bid_n=19813766fbc06248994ca7; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221981376709c220-0cef6cca8d731c8-26011e51-2073600-1981376709d9b4%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTk4MTM3NjcwOWMyMjAtMGNlZjZjY2E4ZDczMWM4LTI2MDExZTUxLTIwNzM2MDAtMTk4MTM3NjcwOWQ5YjQifQ%3D%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%22%2C%22value%22%3A%22%22%7D%2C%22%24device_id%22%3A%221981376709c220-0cef6cca8d731c8-26011e51-2073600-1981376709d9b4%22%7D; Hm_lvt_65968db3ac154c3089d7f9a4cbb98c94=1753105623; _ga=GA1.1.282458238.1752673184; _ga_FKHKQM5HWS=GS2.2.s1753105623$o1$g1$t1753105623$j60$l0$h0; yaozh_logintime=1753105831; yaozh_logintime_ext=1753105831; yaozh_user=1537877%09yaozh_15201065686; yaozh_user_ext=1537877%09yaozh_15201065686; yaozh_userId=1537877; yaozh_userId_ext=1537877; yaozh_jobstatus=kptta67UcJieW6zKnFSe2JyYnoaSbJhsnZucg26qb21rg66flM6bh5%2BscZJvbIXew9DezMBommeVlZWXaG1tblOcrGtsm1jRxayrwKyb0Mq59Bf914E8064150A2f8C35f5eeF11fa6EnNeekmefV5abmpRjb2xoaJdbbKabap%2BGraDOnVSe2JySl56DaJxqmJWVlmtqZmxqmltssA%3D%3D53b8bc239ecb64f4369d0d486cca0327; _ga=GA1.3.282458238.1752673184; _gid=GA1.3.2103832457.1753105615; _c_WBKFRo=POXx8UcSMXP2Zk0qz9yks5JlgxPBqgLC0fLRxItx; _clck=1iirlss%7C2%7Cfxu%7C0%7C2023; PHPSESSID=6kuvfpoqdea1jg92j7275okbh2; Path=/; Hm_lvt_19d20990a54a49c29ef6894ac385ed90=1752673184,1753105614,1753244143; HMACCOUNT=8134B8F59C308B5F; Hm_lvt_k8xnbso1idm=1752673184,1753105615,1753244144; Hm_lvt_be8cc362c4e40bc680a230dd3610a66f=1752673184,1753105615,1753244144; kztoken=nJail6zJp6iXaJqWmW5lYmduYZOT; his=a%3A10%3A%7Bi%3A0%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYWpoY5aY%22%3Bi%3A1%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYWpsY5aZ%22%3Bi%3A2%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmVoapaY%22%3Bi%3A3%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmVpYZuT%22%3Bi%3A4%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmVpYZuY%22%3Bi%3A5%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmVrZpaa%22%3Bi%3A6%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdrZ5WU%22%3Bi%3A7%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdraJyU%22%3Bi%3A8%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmdtapyT%22%3Bi%3A9%3Bs%3A28%3A%22nJail6zJp6iXaJqWmW5lYmduYZOT%22%3B%7D; search_number=24; _currentUrl_=%2FIndex%2FgetRecSupply%3Fcallback%3DjQuery112405366185238180221_1753266005767%26search%3D%25E4%25B9%259D%25E5%2591%25B3%25E7%25BE%258C%25E6%25B4%25BB%25E4%25B8%25B8%26_%3D1753266005768; acw_tc=1a0c39a017532680622438492e008572c4d31e022e49050c413fcddbc2a00a; acw_sc__v3=6880bf62e1084000efe52608d25a88ec5ce93d12; think_language=zh-CN; _vipuser_instruct_auth_=instruct; Hm_lpvt_19d20990a54a49c29ef6894ac385ed90=1753268067; _gat=1; Hm_lpvt_be8cc362c4e40bc680a230dd3610a66f=1753268067; Hm_lpvt_k8xnbso1idm=1753268067; _clsk=12ioegw%7C1753268067821%7C2%7C1%7Cl.clarity.ms%2Fcollect; _ga_W6DF8W4GMP=GS2.1.s1753268056$o17$g1$t1753268072$j44$l0$h0";
                WebDriver webDriver = getWebDriver(cookie, "https://db.yaozh.com");
                webDriver.get("https://db.yaozh.com/instruct?comprehensivesearchcontent="+medicineName);
                WebDriverWait webDriverWait = newWebDriverWait();
                webDriverWait.until(ExpectedConditions.presenceOfElementLocated(
                        By.cssSelector("div.main")));
                // 获取渲染后的页面源码
                String pageSource = webDriver.getPageSource();
                // 使用JSoup解析
                Document document = Jsoup.parse(pageSource);
                Elements tables = document.select("table[data-widget=responsivetable]");
                //        // ... existing code ...
                Element contentTable = tables.first();
                if (null == contentTable){
                    continue;
                }
                Elements trs = contentTable.select("tbody tr");
                if (trs.isEmpty()){
                    continue;
                }

                // 获取分页信息
                Element pagination = document.select("div[data-widget=dbPagination]").first();
                int currentPage = Integer.parseInt(pagination.attr("data-page"));
                int totalRecords = Integer.parseInt(pagination.attr("data-total"));
                int pageSize = Integer.parseInt(pagination.attr("data-size"));
                int totalPages = (int) Math.ceil((double)totalRecords / pageSize);
                log.info("totalRecords:{},pageSize:{},totalPages:{}",totalRecords,pageSize,totalPages);

                // 用于存储最新记录
                String latestMedicineName = "";
                String latestModifyDate = "";
                String latestFullTextUrl = "";
                int targetPage = 1;

                String noDataMedicineName = "";
                String noDataInstructionSource = "";
                String noDataPackageImage = "";
                String noDataFullText = "";
                String noDataModifyDate = "";
                String noDataFullTextUrl = "";


                // 遍历所有页面
                for(int page = 1; page <= totalPages; page++) {
                    System.out.println("正在处理第"+page+"页..."+medicineName);

                    if(page > 1) {
                        // 翻页处理
                        webDriver.get("https://db.yaozh.com/instruct?comprehensivesearchcontent="+medicineName+"&p="+page);
                        try {
                            webDriverWait.until(ExpectedConditions.presenceOfElementLocated(
                                    By.cssSelector("div.main")));
                        } catch (Exception e){
                            exportExcel(medicineInfoResults, noDataResults, outputPath);
                            log.error("遇到验证码或页面加载失败，药品编号：{} - {}", i + 1, medicineInfo.getMedicineName());
                        }
                        document = Jsoup.parse(webDriver.getPageSource());
                        contentTable = document.select("table[data-widget=responsivetable]").first();
                        trs = contentTable.select("tbody tr");
                    }

                    // 处理当前页数据
                    for (Element tr : trs) {
                        Elements tds = tr.select("td");
                        // ... existing code ...
                        String medicineNameTitle = tds.get(0).text();
                        String instructionSource = tds.get(1).text();
                        String packageImage = tds.get(3).select("img").attr("src");
                        String modifyDate = tds.get(2).text();

                        // 获取查看全文列内容
                        Element viewFullTextLink = tds.get(4).select("a.cl-blue").first();
                        String fullTextUrl = "";
                        String fullText = "";
                        if(viewFullTextLink != null) {
                            fullText = viewFullTextLink.text();
                            // 情况2：直接查看全文(href属性)
                            if(viewFullTextLink.hasAttr("href")) {
                                String href = viewFullTextLink.attr("href");
                                if (href.contains("fdown(")){
                                    href = href.replace("javascript:fdown(\"", "")
                                            .replace("\");", "");
                                    fullTextUrl = "https://db.yaozh.com" + href;
                                } else {
                                    fullTextUrl = "https://db.yaozh.com" + href;
                                }
                            }
                        }
                        // ... existing code ...

                        // 比较日期，找出最新记录
                        if(medicineName.equals(medicineNameTitle) && modifyDate.compareTo(latestModifyDate) > 0 && "查看全文".equals(fullText)) {
                            latestModifyDate = modifyDate;
                            targetPage = page;
                            latestFullTextUrl = fullTextUrl;
                        }

                        if(medicineName.equals(medicineNameTitle) &&modifyDate.compareTo(latestModifyDate) > 0) {
                            // 获取下载链接
                            noDataModifyDate = modifyDate;
                            noDataFullTextUrl = fullTextUrl;
                            noDataMedicineName = medicineNameTitle;
                            noDataInstructionSource = instructionSource;
                            noDataPackageImage = packageImage;
                            noDataFullText = fullText;
                        }
                    }

                    // 添加延迟防止被封
                    Thread.sleep(700 + new Random().nextInt(700));
                }

                // 跳转到最新记录所在页面
                if (!latestFullTextUrl.isEmpty()){
                    System.out.println("最新记录在第"+targetPage+"页");
                    // 添加延迟防止被封
                    webDriver.get(latestFullTextUrl);
                    webDriverWait.until(ExpectedConditions.presenceOfElementLocated(
                            By.cssSelector("div.manual")));
                    document = Jsoup.parse(webDriver.getPageSource());

                    MedicineInfo parseMedicineInfo = MedicineHtmlParser.parse(document);
                    System.out.println(JSON.toJSONString(parseMedicineInfo));
                    // ... existing code ...
                    medicineInfoResults.add(parseMedicineInfo);
                } else {
                    System.out.println("没有找到符合条件的记录");
                    MedicineInstruction medicineInstruction = new MedicineInstruction();
                    medicineInstruction.setMedicineName( noDataMedicineName);
                    medicineInstruction.setInstructionSource( noDataInstructionSource);
                    medicineInstruction.setPackageImageUrl( noDataPackageImage);
                    medicineInstruction.setViewFullText( noDataFullText);
                    medicineInstruction.setViewFullTextLink( noDataFullTextUrl);
                    medicineInstruction.setModifyDate( noDataModifyDate);
                    noDataResults.add(medicineInstruction);
                }
            }
            exportExcel(medicineInfoResults, noDataResults, outputPath);
        } catch (Exception e){
            e.printStackTrace();
            log.error("数据处理异常：{}", e.getMessage());
            if (medicineInfoResults.size() > 10){
                exportExcel(medicineInfoResults, noDataResults, outputPath);
            } else {
                log.info("数据不高于10条，未保存");
            }
        }
    }

    private static List<MedicineInfo> readExcel(String filePath) {
        return EasyExcel.read(filePath)
                .head(MedicineInfo.class)
                .sheet()
                .doReadSync();
    }

    public static void exportExcel(List<MedicineInfo> medicineInfoResults,
                                   List<MedicineInstruction> noDataResults,
                                   String outputFilePath) {

        // 1. 创建 ExcelWriter 对象（核心）
        ExcelWriter excelWriter = EasyExcel.write(outputFilePath).build();

        try {
            // 2. 写入第一个 Sheet
            WriteSheet sheet1 = EasyExcel.writerSheet("符合爬取条件的数据")
                    .head(MedicineInfo.class)
                    .registerWriteHandler(new CustomColumnWidthStrategy())
                    .registerWriteHandler(new CustomCellStyleStrategy())
                    .build();

            excelWriter.write(medicineInfoResults, sheet1);

            // 3. 写入第二个 Sheet
            WriteSheet sheet2 = EasyExcel.writerSheet("不符合爬取条件的数据")
                    .head(MedicineInstruction.class)
                    .registerWriteHandler(new CustomColumnWidthStrategy())
                    .registerWriteHandler(new CustomCellStyleStrategy())
                    .build();

            excelWriter.write(noDataResults, sheet2);

            System.out.println("Excel 已成功生成两个 Sheet 于: " + outputFilePath);
        } finally {
            // 4. 必须关闭 writer 释放资源
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    private static String formatElapsedTime(long millis) {
        long seconds = millis / 1000;
        long hours = seconds / 3600;
        seconds %= 3600;
        long minutes = seconds / 60;
        seconds %= 60;
        return String.format("%02d小时%02d分%02d秒", hours, minutes, seconds);
    }



}
